/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
// Local
#include "misc.h"
#include "xmldico.h"

// QtCore
#include <QtGlobal>

// QtXml
#include <QDomNode>
#include <QDomElement>
#include <QDomDocument>
#include <QDomNodeList>
#include <QDomText>

Misc::Misc(const QString &iName, int iVersion, MiscType iType, MiscUse iUse, const Duration &iTime, const Volume &iAmount)
:BeerXMLObject(iName,iVersion)
,_Type(iType)
,_Use(iUse)
,_Time(iTime)
,_AmountV(iAmount)
,_AmountW(0.0)
,_AmountIsWeight(false)
,_UseFor()
,_Notes()
{
}

Misc::Misc(const QString &iName, int iVersion, MiscType iType, MiscUse iUse, const Duration &iTime, const Weight &iAmount)
:BeerXMLObject(iName,iVersion)
,_Type(iType)
,_Use(iUse)
,_Time(iTime)
,_AmountV(0.0)
,_AmountW(iAmount)
,_AmountIsWeight(true)
,_UseFor()
,_Notes()
{
}

Misc::Misc()
:BeerXMLObject()
,_Type(MTSpice)
,_Use(MUBoil)
,_Time(0.0)
,_AmountV(0.0)
,_AmountW(0.0)
,_AmountIsWeight(false)
,_UseFor()
,_Notes()
{
}

Misc::~Misc()
{
}

bool Misc::operator==(const Misc &iOther) const
{
    return ((*this).BeerXMLObject::operator==(iOther) &&
            _Type == iOther._Type &&
            _Use == iOther._Use &&
            _Time == iOther._Time &&
            _AmountV == iOther._AmountV &&
            _AmountW == iOther._AmountW &&
            _AmountIsWeight == iOther._AmountIsWeight &&
            _UseFor == iOther._UseFor &&
            _Notes == iOther._Notes);
}

bool Misc::operator !=(const Misc &iOther) const
{
    return (!((*this)==iOther));
}

int Misc::CreateFromXMLNode(const QDomNode &iNode)
{
    int oRC = 1;
    if (!iNode.isNull())
    {
        QDomElement MiscElement;

        // Case Document : check if doc has only one Hop element
        if (iNode.isDocument())
        {
            QDomDocument MiscDoc = iNode.toDocument();
            QDomNodeList MiscList = MiscDoc.elementsByTagName(MISC);
            if (MiscList.length()==1)
                MiscElement = MiscList.item(0).toElement();
        }
        // Default : cast to element
        else
            MiscElement = iNode.toElement();

        // Check element consistency
        if (!MiscElement.isNull() && MISC==MiscElement.tagName())
        {
            // Check existence of mandatory elements
            bool MiscName = false;
            bool MiscVersion = false;
            bool MiscType = false;
            bool MiscAmount = false;
            bool MiscTime = false;
            bool MiscUse = false;
            QString strAmount;
            QDomNode node = MiscElement.firstChild();
            while (!node.isNull())
            {
                if (node.isElement())
                {
                    QDomElement elem = node.toElement();
                    QString name = elem.tagName();
                    QString text = elem.text();
                    if (name==MISC_NAME)
                    {
                        _Name = text;
                        MiscName = true;
                    }
                    else if (name==MISC_VERSION)
                    {
                        bool ok = false;
                        int v = text.toInt(&ok);
                        if (ok)
                        {
                            _Version = v;
                            MiscVersion = true;
                        }
                    }
                    else if (name==MISC_TYPE)
                    {
                        MiscType = true;
                        QString type = text.toLower();
                        if (type==MISC_TYPE_SPICE.toLower())
                            _Type = MTSpice;
                        else if (type==MISC_TYPE_FINING.toLower())
                            _Type = MTFining;
                        else if (type==MISC_TYPE_WATERAGENT.toLower())
                            _Type = MTWaterAgent;
                        else if (type==MISC_TYPE_HERB.toLower())
                            _Type = MTHerb;
                        else if (type==MISC_TYPE_FLAVOR.toLower())
                            _Type = MTFlavor;
                        else if (type==MISC_TYPE_OTHER.toLower())
                            _Type = MTOther;
                        else
                            MiscType = false;
                    }
                    else if (name==MISC_USE)
                    {
                        MiscUse = true;
                        QString use = text.toLower();
                        if (use==MISC_USE_BOIL.toLower())
                            _Use = MUBoil;
                        else if (use==MISC_USE_MASH.toLower())
                            _Use = MUMash;
                        else if (use==MISC_USE_PRIMARY.toLower())
                            _Use = MUPrimary;
                        else if (use==MISC_USE_SECONDARY.toLower())
                            _Use = MUSecondary;
                        else if (use==MISC_USE_BOTTLING.toLower())
                            _Use = MUBottling;
                        else
                            MiscUse = false;
                    }
                    else if (name==MISC_TIME)
                    {
                        bool ok = false;
                        _Time.FromString(text,&ok);
                        if (ok)
                            MiscTime = true;
                    }
                    else if (name==MISC_AMOUNT)
                    {
                        strAmount = text;
                        MiscAmount = true;
                    }
                    else if (name==MISC_AMOUNTISWEIGHT)
                    {
                        if (text.toLower()=="true")
                            _AmountIsWeight = true;
                    }
                    else if (name==MISC_USEFOR)
                    {
                        _UseFor = text;
                    }
                    else if (name==MISC_NOTES)
                        _Notes = text;
                }

                // Iterate
                node = node.nextSibling();
            }

            // Check & update output
            if (MiscName && MiscVersion && MiscType && MiscAmount && MiscTime && MiscUse)
            {
                bool ok = false;
                if (_AmountIsWeight)
                    _AmountW.FromString(strAmount,&ok);
                else
                    _AmountV.FromString(strAmount,&ok);

                if (ok)
                {
                    oRC = 0;
                }
            }
        }
    }
    return oRC;
}


int Misc::ToXMLNode(QDomNode &iParentNode) const
{
    int oRC = 1;

    // First, create valid element node
    QDomDocument doc = iParentNode.ownerDocument();
    QDomElement MiscNode = doc.createElement(MISC);
    if (!MiscNode.isNull())
    {
        if (!_Name.isEmpty() && _Version>0)
        {
            QDomElement node;
            QDomText textNode;
            QString str;

            // Name
            node = doc.createElement(MISC_NAME);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(_Name);
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MiscNode.appendChild(node);

            // Version
            node = doc.createElement(MISC_VERSION);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Version));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MiscNode.appendChild(node);

            // Type
            switch (_Type)
            {
            case MTSpice:
                str = MISC_TYPE_SPICE;
                break;
            case MTFining:
                str = MISC_TYPE_FINING;
                break;
            case MTWaterAgent:
                str = MISC_TYPE_WATERAGENT;
                break;
            case MTHerb:
                str = MISC_TYPE_HERB;
                break;
            case MTFlavor:
                str = MISC_TYPE_FLAVOR;
                break;
            case MTOther:
                str = MISC_TYPE_OTHER;
                break;
            }
            node = doc.createElement(MISC_TYPE);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(str);
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MiscNode.appendChild(node);

            // Use
            switch (_Use)
            {
            case MUBoil:
                str = MISC_USE_BOIL;
                break;
            case MUMash:
                str = MISC_USE_MASH;
                break;
            case MUPrimary:
                str = MISC_USE_PRIMARY;
                break;
            case MUSecondary:
                str = MISC_USE_SECONDARY;
                break;
            case MUBottling:
                str = MISC_USE_BOTTLING;
                break;
            }
            node = doc.createElement(MISC_USE);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(str);
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MiscNode.appendChild(node);

            // Time
            node = doc.createElement(MISC_TIME);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Time.Value(Minute)));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MiscNode.appendChild(node);

            // Amount
            if (_AmountIsWeight)
            {
                // Weight
                str = QString::number(_AmountW.Value(Kilogram));

                // Write flag
                node = doc.createElement(MISC_AMOUNTISWEIGHT);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode("TRUE");
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                MiscNode.appendChild(node);
            }
            else
            {
                // Volume
                str = QString::number(_AmountV.Value(Liter));
            }
            node = doc.createElement(MISC_AMOUNT);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(str);
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MiscNode.appendChild(node);

            // Use for
            if (!_UseFor.isEmpty())
            {
                node = doc.createElement(MISC_USEFOR);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode(_UseFor);
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                MiscNode.appendChild(node);
            }

            // notes
            if (!_Notes.isEmpty())
            {
                node = doc.createElement(MISC_NOTES);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode(_Notes);
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                MiscNode.appendChild(node);
            }

            // Update output
            QDomNode zeNode = iParentNode.appendChild(MiscNode);
            if (!zeNode.isNull())
                oRC = 0;
        }
    }

    return oRC;
}
